package itsm.isperp.framework.service;

import itsm.isperp.framework.collection.map.LowercaseKeyHashMap;
import itsm.isperp.framework.data.domain.DataRequest;
import itsm.isperp.framework.data.domain.DataResponse;
import itsm.isperp.framework.domain.IBean;
import itsm.isperp.framework.web.response.ResultMessage;

import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

/**
 * 
 * 基本业务服务接口.用于一般实体bean的业务服务.
 * 
 * @author lizx
 * @date 2013-7-31
 * @since 1.0
 */
public interface IBaseService<T extends IBean> {

	/**
	 * 根据 唯一标识查找实体
	 * 
	 * @param id
	 *            唯一标识
	 * @return 实体
	 */
	public T findOne(String id);

	/**
	 * 查找实体赋值在一个Map中
	 * 
	 * @param id
	 *            唯一标识
	 * @return 实体Map
	 */
	public Map<String, Object> findOneToMap(String id);

	/**
	 * 
	 * 查找实体赋值在一个Map中,其中DataRequest用于指定查询的列
	 * 
	 * @param id
	 *            唯一标识
	 * @param selectColumns
	 *            数据请求
	 * @return 实体Map
	 */
	public Map<String, Object> findOneToMap(String id, String... selectColumns);

	/**
	 * 是否存在指定id的数据，如果为存在返回true
	 * 
	 * @param id
	 *            唯一标识
	 * @return 是否存在
	 */
	public boolean exists(String id);

	/**
	 * 
	 * 根据数据请求返回数据结果
	 * 
	 * @param req
	 *            数据请求
	 * @return 数据结果
	 */
	public DataResponse<T> findAll(DataRequest req);

	/**
	 * 返回所有数据
	 * 
	 * @return 数据结果
	 */
	public DataResponse<T> findAll();

	/**
	 * 查询一个Map的列表
	 * 
	 * @return Map的列表
	 */
	List<LowercaseKeyHashMap<String, Object>> findAllToMap();

	/**
	 * 根据实体 唯一标识删除实体
	 * 
	 * @param id
	 *            唯一标识
	 */
	public ResultMessage delete(String id);

	/**
	 * 动态更新实体，如果指定实体对象的字段不为空则将会持久化到数据库中，如果指定实体为空则将忽略
	 * 
	 * @param entity
	 *            实体
	 */
	// public void dynamicUpdate(T entity);

	/**
	 * 动态更新实体，如果指定实体对象的字段不为空则将会持久化到数据库中，如果指定实体为空则将忽略
	 * 
	 * @param entity
	 *            实体对象
	 */
	// public void dynamicUpdateEntity(T entity);

	/**
	 * 动态更新，但是可以通过unIncludeColumns忽略某些字段的更新
	 * <p>
	 * e.g: <br>
	 * 
	 * {@code MyEntity e= new MyEntity() => id="1",name="Lee",email="" ;
	 * Set<String> sets= new HashSet<>(); sets.add("email"); } <br>
	 * 那么在更新实体时<b>不会</b>对字段email进行更新.
	 * </p>
	 * 
	 * @param entity
	 *            实体
	 * @param unIncludeColumns
	 *            指定实体不需要更新的字段
	 */
	public <S extends T> void dynamicButSpecificUpdate(S entity,
			Set<String> unIncludeColumns);

	/**
	 * 动态更新指定字段的值.
	 * <p>
	 * e.g: <br>
	 * 
	 * {@code MyEntity e= new MyEntity() => id="1",name="Lee",email="" ;
	 * Set<String> sets= new HashSet<>(); sets.add("email"); } <br>
	 * 那么在更新实体时只会对字段email进行更新.
	 * </p>
	 * 
	 * @param entity
	 *            实体
	 * @param includeColumns
	 *            指定实体需要更新的字段的集合
	 */
	public <S extends T> void dynamicUpdateSpecific(S entity,
			Set<String> includeColumns);

	/**
	 * 新增或者更新一个实体
	 * 
	 * @param entity
	 *            实体
	 * @return 结果数
	 */
	public <S extends T> int saveOrUpdate(S entity);

	/**
	 * 动态更新，但是可以通过unIncludeColumns忽略某些字段的更新
	 * <p>
	 * e.g: <br>
	 * 
	 * {@code MyEntity e= new MyEntity() => id="1",name="Lee",email="" ;
	 * Set<String> sets= new HashSet<>(); sets.add("email"); } <br>
	 * 那么在更新实体时<b>不会</b>对字段email进行更新.
	 * </p>
	 * 
	 * @param entity
	 *            实体
	 * @param unIncludeColumns
	 *            指定实体不需要更新的字段
	 */
	public <S extends T> int saveOrUpdateButSpecific(S entity,
			Set<String> unIncludeColumns);

	/**
	 * 动态更新指定字段的值.<br>
	 * 注意:如果实体是新增，则所有字段将会被保存
	 * 
	 * <p>
	 * e.g: <br>
	 * 
	 * {@code MyEntity e= new MyEntity() => id="1",name="Lee",email="" ;
	 * Set<String> sets= new HashSet<>(); sets.add("email"); } <br>
	 * 那么在更新实体时只会对字段email进行更新.
	 * </p>
	 * 
	 * @param entity
	 *            实体
	 * @param includeColumns
	 *            指定实体需要更新的字段的集合
	 */
	public <S extends T> int saveOrUpdateSpecific(S entity,
			Set<String> includeColumns);

	/**
	 * 动态更新请求中指定字段的值.<br>
	 * 注意，如果实体是新增，则所有字段将会被保存
	 * 
	 * 
	 * @see IBaseService#saveOrUpdate(IBean, Set)
	 * @param entity
	 *            实体
	 * @param req
	 *            请求
	 * @return 指定实体需要更新的字段的集合
	 */
	public <S extends T> int saveOrUpdate(S entity, HttpServletRequest req);

	public <S extends T> int saveOrUpdate(S entity, HttpServletRequest req,
			String... otherFields);

	/**
	 * 动态更新请求中指定字段的值.以及指定的字段的值; <br>
	 * 注意:如果实体是新增，则所有字段将会被保存
	 * 
	 * @see IBaseService#saveOrUpdate(IBean, Set)
	 * @param entity
	 *            实体
	 * @param req
	 *            请求
	 * @param otherFields
	 *            其他需要保持或者更新的字段
	 * @return 指定实体需要更新的字段的集合
	 */
	public <S extends T> int saveOrUpdateAndSpecific(S entity,
			HttpServletRequest req, String... otherFields);

}
